/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.is.ga;

import java.util.LinkedList;

/**
 *  Класс хромосомы. Хромосома представлена массивом номеров городов.
 *  - это последовательность городов
 * @author oleg
 */
public class Chromosome implements Comparable<Chromosome> {

    int chromosome[];
    double matrix[][];
    double cost;
    
    public Chromosome(int[] chromosome, double[][] matrix) {
        this.chromosome = chromosome;
        this.matrix = matrix;
        initCost();
    }

    private Chromosome(Integer[] array, double[][] matrix) {
        chromosome=new int[array.length];
        System.arraycopy(array, 0, chromosome, 0, array.length);
        this.matrix=matrix;
    }

    private void initCost(){
        this.cost=getCost();
    }
    
    public double getCost() {
        double result = 0;//matrix[0][this.getChromosome()[0]];
        for (int i = 0; i < chromosome.length - 1; i++) {
            result += matrix[this.getChromosome()[i]][this.getChromosome()[i+1]];
        }
        //result+=matrix[this.getChromosome()[this.getChromosome().length-1]][this.getChromosome()[0]];
        return result;
    }

    public double crossedCost(Chromosome chr) {
        double result = 0;

        return result;
    }

    private int getTownIndex(int town) {
        for (int i = 0; i < chromosome.length; i++) {
            if (town == chromosome[i]) {
                return i;
            }
        }
        return -1;
    }

    public int[] getChromosome() {
        return chromosome;
    }

    public void setCost(double cost) {
        this.cost = cost;
    }

    
    
    public Chromosome cross(Chromosome b) {
        boolean atrue = true;
        boolean btrue = true;
        LinkedList<Integer> newChromosome = new LinkedList<Integer>();
        int town = (int) (Math.random() * chromosome.length);
        int x = this.getTownIndex(town);
        int y = b.getTownIndex(town);
        newChromosome.add(town);
        while ((atrue || btrue)&&(newChromosome.size()<this.chromosome.length)) {
            if (x == 0) {
                x = this.chromosome.length;
            }
            x--;
            if (y == this.chromosome.length-1) {
                y = -1;
            }
            y++;
            if (atrue) {
                if (!newChromosome.contains(this.getChromosome()[x])) {
                    newChromosome.addFirst(this.getChromosome()[x]);
                } else {
                    atrue = false;
                }
            }
            if (btrue) {
                if (!newChromosome.contains(b.getChromosome()[y])) {
                    newChromosome.addLast(b.getChromosome()[y]);
                } else {
                    btrue = false;
                }
            }
        }
        if(newChromosome.size()<this.chromosome.length){
            ChromosomeGenerator array=new ChromosomeGenerator(this.chromosome.length);
            array.exclude(newChromosome);
            while(newChromosome.size()<this.chromosome.length){
                newChromosome.add(array.getRandom());
            }
        }
        int array[]=new int[newChromosome.size()];
        for(int i=0;i<this.chromosome.length;i++)
            array[i]=newChromosome.get(i);
        return new Chromosome(array, matrix);
    }

    @Override
    public int compareTo(Chromosome o) {
        if(this.getCost()>o.getCost())
            return 1;
        else if(this.getCost()<o.getCost())
            return -1;
        else
            return 0;
    }
}
